home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1829 < prev    next >
Encoding:
Internet Message Format  |  1990-12-28  |  39.9 KB

  1. From: tin@szebra.szebra.uucp (Tin Le)
  2. Newsgroups: alt.sources
  3. Subject: ST-0x 386/ix driver v1.0 pt3/6
  4. Message-ID: <1990Sep17.063006.25572@szebra.uucp>
  5. Date: 17 Sep 90 06:30:06 GMT
  6.  
  7. Seagate ST-0x 386/ix driver v1.0
  8.  
  9. #!/bin/sh
  10. # this is st02.03 (part 3 of a multipart archive)
  11. # do not concatenate these parts, unpack them in order with /bin/sh
  12. # file scsi.c continued
  13. #
  14. if test ! -r _shar_seq_.tmp; then
  15.     echo 'Please unpack part 1 first!'
  16.     exit 1
  17. fi
  18. (read Scheck
  19.  if test "$Scheck" != 3; then
  20.     echo Please unpack part "$Scheck" next!
  21.     exit 1
  22.  else
  23.     exit 0
  24.  fi
  25. ) < _shar_seq_.tmp || exit 1
  26. if test ! -f _shar_wnt_.tmp; then
  27.     echo 'x - still skipping scsi.c'
  28. else
  29. echo 'x - continuing file scsi.c'
  30. sed 's/^X//' << 'SHAR_EOF' >> 'scsi.c' &&
  31. X
  32. static void startbufferio(unit,bp)
  33. int unit;
  34. struct buf *bp;
  35. {
  36. X  dorw(unit,BLPTOSEC(unit,PARTNO(minor(bp->b_dev)),bp->b_blkno),
  37. X       bp->b_un.b_addr,bp->b_bcount,bp->b_flags,0,bp);
  38. }
  39. X
  40. /* This will start a pending io request in the system.  If bp (the previous
  41. X   request) is non-NULL, this will first remove bp from the list of
  42. X   pending requests.  This will then start a new request if there are any.
  43. X   This can only be called with splnointrs, and when the unit is not busy. */
  44. X
  45. static void startpendingreq(unit,bp)
  46. int unit;
  47. struct buf *bp;
  48. {
  49. X  register struct buf *ap;
  50. X  register int x;
  51. X
  52. X  x=splnointrs();
  53. X  if (bp)
  54. X    {
  55. X      ap=bp->av_forw;
  56. X      if (!ap)
  57. X        if (d[unit].reqlist != bp)
  58. X          ap=d[unit].reqlist;
  59. X    }
  60. X   else
  61. X    ap=d[unit].reqlist;
  62. X  /* ap is the next request to process, or NULL if there are none pending. */
  63. X  if (bp)
  64. X    {
  65. X      if (bp == d[unit].reqlist)
  66. X        d[unit].reqlist=bp->av_forw;
  67. X      if (bp->av_back)
  68. X        bp->av_back->av_forw=bp->av_forw;
  69. X      if (bp->av_forw)
  70. X        bp->av_forw->av_back=bp->av_back;
  71. X      bp->av_forw=NULL;
  72. X      bp->av_back=NULL;
  73. X      /* bp has now been removed from the list of requests. */
  74. X    }
  75. X
  76. X  if (ap) /* start the next pending request if there are any */
  77. X    startbufferio(unit,ap);
  78. X
  79. X  splx(x);
  80. }
  81. X
  82. /* This marks the unit not busy.  This is used to mark the completion
  83. X   of a command.  This must absolutely be called exactly once for each and
  84. X   every i/o request made.  If the request was for an io buffer, this will
  85. X   set b_flags&B_ERROR according to the completion; COK marks good completion.
  86. X   If there are any processes sleeping for the drive to become not busy,
  87. X   this will wake them up.  If there is any pending block io, this will
  88. X   start i/o for the next buffer.  After a call to this, all data in the
  89. X   d[unit] structure for the previous request will have been lost and the
  90. X   next operation may be in progress. The scsi driver and controller should
  91. X   be set to bus free phase before calling this. */
  92. X
  93. static void marknotbusy(unit,completion)
  94. int unit,completion;
  95. {
  96. X  register int x;
  97. X  register struct buf *ap;
  98. X
  99. #ifdef DEBUG0
  100. X  printf("scsi: marknotbusy unit=%d completion=%d\n",
  101. X         unit,completion);
  102. #endif
  103. X  x=splnointrs();
  104. X  d[unit].busy=0;
  105. X  d[unit].connected=0; /* just in case */
  106. X  d[unit].xfertime=0; /* we don't want any timeouts any more */
  107. X  ap=d[unit].currentbuf;
  108. X  if (ap)
  109. X    {
  110. X      if (completion != COK)
  111. X        ap->b_flags|=B_ERROR;
  112. X    }
  113. X   else
  114. X    if (!d[unit].xferpolled)
  115. X      wakeup(&d[unit].connected);
  116. X  startpendingreq(unit,ap); /* This will start any pending io */
  117. X  if (ap)
  118. X    iodone(ap);
  119. #ifdef DEBUG0
  120. X  printf("scsi: marknotbusy returning\n");
  121. #endif
  122. X  splx(x);
  123. }
  124. X
  125. /* This is the scsi interrupt service routine.  This is called with a priority
  126. X   lower than that of the timer tick, which is used to detect timeouts.
  127. X   This is called (this ignores other calls) when a target is reselecting this
  128. X   initiator.  This will continue processing the reconnected request, and
  129. X   if the request completes, this will (in lower-level routines) start the
  130. X   next request automatically. */
  131. X
  132. void scsiintr()
  133. {
  134. X  register int a;
  135. X  register int x;
  136. X  register int unit;
  137. X  long l;
  138. X
  139. X  if (!(*cmdport & STSEL))
  140. X    {
  141. #ifdef DEBUG0
  142. X      printf("scsi: intr ignored (no SEL)\n");
  143. #endif
  144. X      return; /* The controller should only generate interrupts when select
  145. X                 rises. */
  146. X    }
  147. X  for (l=0;l<20000l;l++)
  148. X    if (*cmdport & STIO)
  149. X      goto gotio;
  150. #ifdef DEBUG0
  151. X  printf("scsi: intr ignored (IO timeout)\n");
  152. #endif
  153. X  return;
  154. X gotio:
  155. X  a=(*scsidataport) & 0xff;
  156. X  if (!(a & MYADDR))
  157. X    {
  158. #ifdef DEBUG
  159. X      printf("scsi: intr ignored (not my addr); addr=%x\n",a);
  160. #endif
  161. X      return;
  162. X    }
  163. X  a&=(~MYADDR);
  164. X  for (unit=0;unit < 8;unit++)
  165. X    if (a & (unsigned char)(1<<unit))
  166. X      break;
  167. X  if (unit >= 8 || (a & ~(unsigned char)(1<<unit)))
  168. X    {
  169. #ifdef DEBUG
  170. X      printf("scsi: intr ignored (invalid id); unit=%d a=%x\n",unit,a);
  171. #endif
  172. X      return;
  173. X    }
  174. X  if (unit >= SCSIMAXDRIVES)
  175. X    {
  176. #ifdef DEBUG
  177. X      printf("scsi: intr ignored (unit %d >= SCSIMAXDRIVES %d)\n",
  178. X             unit,SCSIMAXDRIVES);
  179. #endif
  180. X      return;
  181. X    }
  182. X  x=splnointrs();
  183. X  if (d[unit].connected || !d[unit].busy)
  184. X    {
  185. #ifdef DEBUG
  186. X      printf("scsi: intr ignored (internal state): unit=%d connected=%d busy=%d\n",
  187. X             unit,d[unit].connected,d[unit].busy);
  188. #endif
  189. X      splx(x);
  190. X      return;
  191. X    }
  192. X  if (d[unit].xferpolled)
  193. X    { /* ooops... This is not the way it was supposed to happen... */
  194. #ifdef DEBUG
  195. X      printf("scsi: intr ignored (xfer is polled); unit=%d\n",unit);
  196. #endif
  197. X      splx(x);
  198. X      return;
  199. X    }
  200. X  *cmdport=CMDBASE|CMDBSY|CMDENABLE; /* acknowledge reselection */
  201. X  for (l=0;l<20000l;l++)
  202. X    if (!(*cmdport & STSEL))
  203. X      goto selreleased;
  204. X  /* timeout waiting for sel to be released */
  205. X  *cmdport=CMDBASE;
  206. #ifdef DEBUG
  207. X  printf("scsi: intr ignored (timeout waiting for SEL to be released); unit=%d\n",
  208. X         unit);
  209. #endif
  210. X  splx(x);
  211. X  return;
  212. X selreleased:
  213. X  for (l=0;l<20000l;l++)
  214. X    if (*cmdport & STBSY)
  215. X      goto selectedandhavebsy;
  216. X  /* timeout waiting for sel to be released */
  217. X  *cmdport=CMDBASE;
  218. #ifdef DEBUG
  219. X  printf("scsi: intr ignored (timeout waiting for BSY after SEL to be released); unit=%d\n",
  220. X         unit);
  221. #endif
  222. X  splx(x);
  223. X  return;
  224. X selectedandhavebsy:
  225. X  *cmdport=CMDBASE|CMDENABLE;
  226. X  d[unit].connected=1;
  227. X  d[unit].xfertime=0;
  228. X  intrserviced=1;
  229. X  splx(x); /* allow timer ticks */
  230. X  if (d[unit].currentbuf)
  231. X    {
  232. X      a=doxfernosleep(unit);
  233. X     doxferbufagain:
  234. X      d[unit].connected=0; /* just in case */
  235. X      if (a != COK && a != CDISCONNECT)
  236. X        { /* We got an error.  We must retry the operation, and if the retry
  237. X             count has elapsed, complete the operation with error. */
  238. X          if (d[unit].xferretries <= 0 || a == CBUSBUSY || a == CNOCONNECT)
  239. X            {
  240. #ifdef DEBUG
  241. X              printf("scsi: intr: cmd failed (%d); returning error\n",a);
  242. #endif
  243. X              *cmdport=CMDBASE;
  244. X              marknotbusy(unit,a); /* This may start a new operation */
  245. X            }
  246. X           else
  247. X            {
  248. X              d[unit].xferretries--;
  249. #ifdef DEBUG
  250. X              printf("scsi: intr: retrying command\n");
  251. #endif
  252. X              a=startscsi(unit); /* this will restart the command */
  253. X              goto doxferbufagain;
  254. X            }
  255. X        }
  256. X    }
  257. X   else
  258. X    { /* it must be an interrupt-driven operation to an internal buffer */
  259. X      wakeup(&d[unit].connected);
  260. X      /* leave the connected indicator on, and do no further processing
  261. X         here.  This will signal the sleeping operation that we are once
  262. X         again connected. */
  263. X    }
  264. X  intrserviced=0;
  265. X  return;
  266. }
  267. X
  268. /* This is called using timeout() every 1/10th of a second.  This is used
  269. X   to solve timeout conditions related to lost interrupts and the like.
  270. X   Note that this is usually entered with a priority higher than that of
  271. X   the scsi driver.  splnointrs should be defined so that this interrupt
  272. X   is also masked out.  There may also be a drawback in using splnointrs:
  273. X   if the system clock is incremented with these timer interrupts, it might
  274. X   lose some ticks when the scsi disk is being used.  I hope Microport has
  275. X   implemented the system clock in some more clever way.  */
  276. X
  277. void scsitick()
  278. {
  279. X  register int a;
  280. X  register int unit;
  281. X  register int x;
  282. X
  283. X  x=splnointrs();
  284. X  if (!intrserviced) /* if in the middle of a scsi interrupt, do nothing */
  285. X    {
  286. X      for (unit=0;unit<SCSIMAXDRIVES;unit++)
  287. X        {
  288. X          if (!d[unit].busy || d[unit].connected || d[unit].xfertime == 0 ||
  289. X              d[unit].xfertimeout == 0 || d[unit].xferpolled)
  290. X            continue;
  291. X          d[unit].xfertime++;
  292. X          if (d[unit].xfertime < d[unit].xfertimeout)
  293. X            continue;
  294. X          /* the timeout has elapsed.  We can only assume that we have lost an
  295. X             interrupt or there are problems on the target which prevent it from
  296. X             reconnecting and completing the command. */
  297. X          d[unit].xfertime=0; /* will be reset in retry if appropriate */
  298. X          if (!d[unit].currentbuf)
  299. X            { /* interrupt-driven transter to local buffer */
  300. #ifdef DEBUG
  301. X              printf("scsi: local intr driven xfer woken up by timer tick; unit=%d\n",
  302. X                     unit);
  303. #endif
  304. X              wakeup(&d[unit].connected); /* !connected tells it to retry */
  305. X              continue;
  306. X            }
  307. X          a=CTIMEOUT;
  308. X         retrytickforbuf:
  309. X          if (a == COK || a == CDISCONNECT)
  310. X            continue;
  311. X          if (d[unit].xferretries == 0 || a == CBUSBUSY || a == CNOCONNECT)
  312. X            {
  313. #ifdef DEBUG
  314. X              printf("scsi: block xfer fails in timer tick; unit=%d, err=%d\n",
  315. X                     unit,a);
  316. #endif
  317. X              marknotbusy(unit,a); /* This may start a new operation */
  318. X              continue;
  319. X            }
  320. X          d[unit].xferretries--;
  321. #ifdef DEBUG
  322. X          printf("scsi: xfer retried in timer tick; unit=%d, err=%d\n",
  323. X                 unit,a);
  324. #endif
  325. X          a=startscsi(unit);
  326. X          goto retrytickforbuf;
  327. X        }
  328. X    }
  329. X  timeout(scsitick,0,TICKSPERSECOND/10);
  330. X  splx(x);
  331. }
  332. X
  333. /* This is the normal strcpy */
  334. X
  335. static void strcpy(d,s)
  336. register unchar *d;
  337. register unchar *s;
  338. {
  339. X  while (*s)
  340. X    *d++=(*s++);
  341. X  *d='\0';
  342. }
  343. X
  344. /* This implements the request sense command.  This returns a C* status. */
  345. X
  346. static int requestsense(unit,buf,len,polled)
  347. int unit,len,polled;
  348. unchar *buf;
  349. {
  350. X  unchar cmd[6];
  351. X
  352. X  if (len > 18)
  353. X    len=18;
  354. X  cmd[0]=SCSIREQSENSE;
  355. X  cmd[1]=0;
  356. X  cmd[2]=0;
  357. X  cmd[3]=0;
  358. X  cmd[4]=len;
  359. X  cmd[5]=0;
  360. X
  361. X  return doscsicmd(unit,cmd,buf,len,2,3,1,0,polled,NULL);
  362. }
  363. X
  364. /* This tests for drive readiness (with the scsi test unit ready command).
  365. X   This returns a C* status. */
  366. X
  367. static int testready(unit)
  368. int unit;
  369. {
  370. X  unchar cmd[6];
  371. X
  372. X  cmd[0]=SCSITESTREADY;
  373. X  cmd[1]=0;
  374. X  cmd[2]=0;
  375. X  cmd[3]=0;
  376. X  cmd[4]=0;
  377. X  cmd[5]=0;
  378. X
  379. X  return doscsicmd(unit,cmd,NULL,0,1,1,1,0,1,NULL);
  380. }
  381. X
  382. /* This issues the inquiry command to the scsi drive to get its drive type
  383. X   and other characteristics.  This returns a C* status. */
  384. X
  385. static int doinquiry(unit,buf,len,polled)
  386. int unit,len,polled;
  387. unchar *buf;
  388. {
  389. X  unchar cmd[6];
  390. X
  391. X  if (len > 36)
  392. X    len=36;
  393. X  cmd[0]=SCSIINQUIRY;
  394. X  cmd[1]=0;
  395. X  cmd[2]=0;
  396. X  cmd[3]=0;
  397. X  cmd[4]=len;
  398. X  cmd[5]=0;
  399. X  return doscsicmd(unit,cmd,buf,len,150,3,1,0,polled,NULL);
  400. X    /* the timeout is quite long to allow time for startup */
  401. }
  402. X
  403. /* This reads the storage capacity and block size of the scsi drive */
  404. X
  405. static int readcapacity(unit,buf,len,polled)
  406. int unit,len,polled;
  407. unchar *buf;
  408. {
  409. X  unchar cmd[10];
  410. X
  411. X  if (len > 8)
  412. X    len=8;
  413. X
  414. X  cmd[0]=SCSIREADCAPACITY;
  415. X  cmd[1]=0;
  416. X  cmd[2]=0;
  417. X  cmd[3]=0;
  418. X  cmd[4]=0;
  419. X  cmd[5]=0;
  420. X  cmd[6]=0;
  421. X  cmd[7]=0;
  422. X  cmd[8]=0;
  423. X  cmd[9]=0;
  424. X
  425. X  if (doscsicmd(unit,cmd,buf,len,150,2,1,0,polled,NULL) != COK)
  426. X    return 0; /* the timeout period is quite long to allow time for startup */
  427. X  return 1;
  428. }
  429. X
  430. /* This is used to initialize the drive at system startup time */
  431. X
  432. static int initdrive(unit)
  433. int unit;
  434. {
  435. X  int a,bs;
  436. X  unchar buf[100];
  437. X  long s,l;
  438. X  unsigned char *cp;
  439. X
  440. X  d[unit].blocksize=0;
  441. X  d[unit].busy=0;
  442. X  d[unit].connected=0;
  443. X  d[unit].nparts=0;
  444. X  d[unit].nomsgs=0;
  445. X
  446. X  a=testready(unit);
  447. X  if (a != COK)
  448. X    {
  449. X      if (a != CERROR && a != CBUSY)
  450. X        return 0;  /* no point in waiting */
  451. X      printf("Waiting for unit %d powerup...\n",unit);
  452. X      for (l=0;l<10000000l;l++)
  453. X        if (l % 100000l == 0)
  454. X          {
  455. X            a=testready(unit);
  456. X            if (a == COK)
  457. X              break;
  458. X          }
  459. X      if (a != COK)
  460. X        {
  461. X          printf("Powerup timeout on drive %d\n",unit);
  462. X          return 0;
  463. X        }
  464. X    }
  465. X  a=requestsense(unit,buf,sizeof(buf),1);
  466. X  if (a == CNOCONNECT || a == CBUSBUSY)
  467. X    return 0;
  468. X  if (a != COK)
  469. X    {
  470. X      printf("scsi drive %d is not responding properly.\n",unit);
  471. X      return 0;
  472. X    }
  473. #ifdef DEBUG0
  474. X  printf("scsi: initdrive: requestsense ok\n");
  475. #endif
  476. X  a=doinquiry(unit,buf,sizeof(buf),1);
  477. X  if (a != COK)
  478. X    {
  479. X      printf("scsi drive %d: inquiry failed.\n",unit);
  480. X      return 0;
  481. X    }
  482. #ifdef DEBUG0
  483. X  printf("scsi: initdrive: doinquiry ok\n");
  484. #endif
  485. X  if (buf[0] != 0)
  486. X    {
  487. X      printf("scsi drive %d is on a direct access device\n",unit);
  488. X      return 0;
  489. X    }
  490. X  buf[buf[4]+6]=0;
  491. X  strcpy(d[unit].drivename,buf+8);
  492. X  if (!readcapacity(unit,buf,sizeof(buf),1))
  493. X    {
  494. X      d[unit].capacity=0;
  495. X      bs=d[unit].blocksize=512;
  496. X      printf("scsi drive %d: cannot read capacity\n",unit);
  497. X    }
  498. X   else
  499. X    {
  500. X      bs=d[unit].blocksize=((unsigned char)buf[6]<<8)+(unsigned char)buf[7];
  501. X      if (bs > BSIZE)
  502. X        printf("scsi drive %d: blocksize=%d BSIZE=%d not supported\n",
  503. X               unit,bs,BSIZE);
  504. X      d[unit].capacity=(long)((unsigned char)buf[0]<<24)+
  505. X                       (long)((unsigned char)buf[1]<<16)+
  506. X                       (long)((unsigned char)buf[2]<<8)+
  507. X                       (long)((unsigned char)buf[3]);
  508. X    }
  509. X  printf("scsi drive %d: %ldMB (%d byte sectors): %s\n",
  510. X         unit,(d[unit].capacity*d[unit].blocksize+524288l)/1048576l,
  511. X         d[unit].blocksize,d[unit].drivename);
  512. X  a=dorw(unit,0l,buf,sizeof(buf),B_READ,1,NULL);
  513. X  if (a != COK)
  514. X    {
  515. X      printf("scsi drive %d: could not read partition table\n",unit);
  516. X      return 0;
  517. X    }
  518. X  for (cp=(unsigned char *)buf,a=0;
  519. X       a<SCSIMAXPARTS-1 &&
  520. X        (cp[0] || cp[1] || cp[2] || cp[3] || cp[4] || cp[5]);
  521. X       a++,cp+=6)
  522. X    {
  523. X      s=(long)(cp[0]<<16)+(cp[1]<<8)+cp[2];
  524. X      l=(long)(cp[3]<<16)+(cp[4]<<8)+cp[5];
  525. X      if (s == 0)
  526. X        {
  527. X          s++;
  528. X          l--;
  529. X        }
  530. X      d[unit].parts[a].start=s;
  531. X      d[unit].parts[a].len=l;
  532. X      if (a == 0)
  533. X        printf("partitions:");
  534. X      printf(" %ldMB",(l*bs+524288l)/1048576l);
  535. X    }
  536. X  if (a != 0)
  537. X    printf("\n");
  538. X  d[unit].nparts=a;
  539. X  d[unit].parts[SCSIMAXPARTS-1].start=0;
  540. X  d[unit].parts[SCSIMAXPARTS-1].len=d[unit].capacity;
  541. X  return 1;
  542. }
  543. X
  544. /*---------------------------------------------------------------------
  545. -- scsiinit()
  546. -----------------------------------------------------------------------*/
  547. void scsiinit()
  548. {
  549. X  register int a;
  550. X  extern char *sptalloc();
  551. X
  552. X  printf("\n%s\n",COPYRIGHT);
  553. X  if (!baseaddr)
  554. X    baseaddr=(unchar *)sptalloc(SCSISIZE/PAGESIZE,PG_P,(int)(SCSIBASE/PAGESIZE),
  555. X                      NOSLEEP);
  556. X  if (!baseaddr)
  557. X    {
  558. X      printf("scsi driver error: could not sptalloc controller memory\n");
  559. X      return;
  560. X    }
  561. X  cmdport=baseaddr+SCSICONTROLOFS;
  562. X  scsidataport=baseaddr+SCSIDATAOFS;
  563. X
  564. X  timeouting=0;
  565. X  for (a=0;a<SCSIMAXDRIVES;a++)
  566. X    {
  567. X      d[a].currentbuf=NULL;
  568. X      d[a].reqlist=NULL;
  569. X    }
  570. X  for (a=0;a<SCSIMAXDRIVES;a++)
  571. X    {
  572. X      initdrive(a);
  573. X    }
  574. X  printf("\n");
  575. }
  576. X
  577. void scsiopen(dev,flags)
  578. dev_t dev;
  579. int flags;
  580. {
  581. X  int unit=UNITNO(minor(dev)),
  582. X      part=PARTNO(minor(dev)),
  583. X      x;
  584. X
  585. #ifdef DEBUG0
  586. X  printf("scsiopen: unit=%d part=%d\n",unit,part);
  587. #endif
  588. X  if (!timeouting)
  589. X    {
  590. X      x=splnointrs(); /* in case scsitick makes any assumptions about spl */
  591. X      scsitick();
  592. X      splx(x);
  593. X      timeouting=1;
  594. X    }
  595. X  if (unit >= SCSIMAXDRIVES ||
  596. X      (part != SCSIMAXPARTS-1 &&
  597. X       (d[unit].blocksize == 0 || part >= d[unit].nparts)))
  598. X    u.u_error=ENXIO;
  599. }
  600. X
  601. void scsiclose()
  602. {
  603. #ifdef DEBUG0
  604. X  printf("scsiclose called\n");
  605. #endif
  606. X  /* do nothing */
  607. }
  608. X
  609. void scsistrategy(bp)
  610. register struct buf *bp;
  611. {
  612. X  int unit=UNITNO(minor(bp->b_dev)),
  613. X      part=PARTNO(minor(bp->b_dev)),
  614. X      nsecs,x;
  615. X  register long sec;
  616. X  register struct buf *ap;
  617. X  register struct buf **app;
  618. X
  619. #ifdef DEBUG0
  620. X  printf("scsistrategy: unit=%d part=%d b_dev=%x b_bcount=%d b_blkno=%d b_flags=%x\n",
  621. X         unit,part,bp->b_dev,bp->b_bcount,bp->b_blkno,bp->b_flags);
  622. #endif
  623. X  if (unit >= SCSIMAXDRIVES || d[unit].blocksize == 0 ||
  624. X      bp->b_bcount % d[unit].blocksize != 0)
  625. X    {
  626. X      bp->b_flags|=B_ERROR;
  627. X      bp->b_resid=bp->b_bcount;
  628. X      iodone(bp);
  629. X      return;
  630. X    }
  631. X  if (part == SCSIMAXPARTS-1)
  632. X    sec=BLTOSEC(unit,bp->b_blkno);
  633. X   else
  634. X    {
  635. X      sec=BLTOSEC(unit,bp->b_blkno);
  636. X      if (part >= d[unit].nparts || sec > d[unit].parts[part].len)
  637. X        {
  638. X          bp->b_flags|=B_ERROR;
  639. X          bp->b_resid=bp->b_bcount;
  640. X          iodone(bp);
  641. X          return;
  642. X        }
  643. X      if (sec == d[unit].parts[part].len)
  644. X        {
  645. X          bp->b_resid=bp->b_bcount;
  646. X          iodone(bp);
  647. X          return;
  648. X        }
  649. X      nsecs=(bp->b_bcount+d[unit].blocksize-1)/d[unit].blocksize;
  650. X      if (sec+nsecs > d[unit].parts[part].len)
  651. X        {
  652. X          nsecs=d[unit].parts[part].len-sec;
  653. X          bp->b_resid=bp->b_bcount-nsecs*d[unit].blocksize;
  654. X        }
  655. X       else
  656. X        bp->b_resid=0;
  657. X      sec+=d[unit].parts[part].start;
  658. X    }
  659. X  x=splnointrs();
  660. X  for (app=(&d[unit].reqlist),ap=NULL;
  661. X       *app;
  662. X       ap=(*app),app=(&(*app)->av_forw))
  663. X    {
  664. X      if (sec < BLPTOSEC(unit,part,(*app)->b_blkno))
  665. X        {
  666. X          bp->av_back=ap;
  667. X          (*app)->av_back=bp;
  668. X          bp->av_forw=(*app);
  669. X          *app=bp;
  670. X          goto haveinserted;
  671. X        }
  672. X    }
  673. X  *app=bp;
  674. X  bp->av_forw=NULL;
  675. X  bp->av_back=ap;
  676. X haveinserted:
  677. X  if (!d[unit].busy)
  678. X    startbufferio(unit,bp);
  679. X  splx(x);
  680. }
  681. X
  682. /* raw io read on the device */
  683. X
  684. void scsiread(dev)
  685. int dev;
  686. {
  687. X  physio(scsistrategy,&scsibuf,dev,B_READ);
  688. }
  689. X
  690. /* raw io write on the device */
  691. X
  692. void scsiwrite(dev)
  693. int dev;
  694. {
  695. X  physio(scsistrategy,&scsibuf,dev,B_WRITE);
  696. }
  697. X
  698. /* This formats the entire scsi drive. */
  699. X
  700. static int formatscsidrive(unit,blocksize,interleave)
  701. int unit,blocksize,interleave;
  702. {
  703. X  unchar cmd[10], buf[12];
  704. X
  705. X  if (blocksize <= 0)
  706. X    blocksize=512;
  707. X  printf("scsi: formatting unit %d with blocksize=%d, interleave=%d\n",
  708. X         unit,blocksize,interleave);
  709. X
  710. X  cmd[0]=SCSIMODESELECT;
  711. X  cmd[1]=0;
  712. X  cmd[2]=0;
  713. X  cmd[3]=0;
  714. X  cmd[4]=12;
  715. X  cmd[5]=0;
  716. X
  717. X  buf[0]=0;
  718. X  buf[1]=0;
  719. X  buf[2]=0;
  720. X  buf[3]=8;
  721. X  buf[4]=0;
  722. X  buf[5]=0;
  723. X  buf[6]=0;
  724. X  buf[7]=0;
  725. X  buf[8]=0;
  726. X  buf[9]=(unchar)(blocksize>>16 & 0xff);
  727. X  buf[10]=(unchar)(blocksize>>8 & 0xff);
  728. X  buf[11]=(unchar)(blocksize & 0xff);
  729. X
  730. X  if (doscsicmd(unit,cmd,buf,12,5,2,1,0,0,NULL) != COK)
  731. X    printf("scsi: warning: mode select command returned error from drive %d\n",
  732. X           unit);
  733. X  cmd[0]=SCSIFORMATUNIT;
  734. X  cmd[1]=0; /* primary and grown defect list only */
  735. X  cmd[2]=0; /* data pattern */
  736. X  cmd[3]=(unchar)(interleave>>8 & 0xff);
  737. X  cmd[4]=(unchar)(interleave & 0xff);
  738. X  cmd[5]=0;
  739. X
  740. X  if (doscsicmd(unit,cmd,NULL,0,0,0,1,0,0,NULL) != COK)
  741. X    {
  742. X      printf("scsi: format failure.\n");
  743. X      return 0;
  744. X    }
  745. X  printf("scsi: format complete.\n");
  746. X  return 1;
  747. }
  748. X
  749. /* This checks that the current user is the super-user.  Returns 0 if not. */
  750. X
  751. static int chksuper()
  752. {
  753. X  if (u.u_uid != 0)
  754. X    {
  755. X      u.u_error=EPERM;
  756. X      return 0;
  757. X    }
  758. X  return 1;
  759. }
  760. X
  761. /* ioctl() for this device */
  762. X
  763. int scsiioctl(dev,cmd,arg,mode)
  764. int dev, cmd, mode;
  765. unchar *arg;
  766. {
  767. X  int unit=UNITNO(minor(dev)),
  768. X      part=PARTNO(minor(dev));
  769. X  unchar *cp;
  770. X
  771. #ifdef DEBUG0
  772. X  printf("scsiioctl: unit=%d part=%d cmd=%d arg=%lx mode=%d\n",
  773. X         unit,part,cmd,arg,mode);
  774. #endif /* DEBUG */
  775. X
  776. X  u.u_error=0;
  777. X  if (unit >= SCSIMAXPARTS ||
  778. X      (part != SCSIMAXPARTS-1 && part >= d[unit].nparts))
  779. X    {
  780. X      u.u_error=EINVAL;
  781. X      return(1);
  782. X    }
  783. X  switch (cmd)
  784. X    {
  785. X      case SCSIIOREADCAP:
  786. X        if (part == 15)
  787. X          suword((int *)arg,(int)d[unit].capacity);
  788. X         else
  789. X          suword((int *)arg,(int)d[unit].parts[part].len);
  790. X        break;
  791. X      case SCSIIOREADTYPE:
  792. X        for (cp=d[unit].drivename;*cp;cp++,arg++)
  793. X          subyte(arg,*cp);
  794. X        subyte(arg,0);
  795. X        break;
  796. X      case SCSIIOSETBLK:
  797. X        if (!chksuper())
  798. X          break;
  799. X        d[unit].blocksize=fuword((int *)arg);
  800. X        break;
  801. X      case SCSIIOFORMAT:
  802. X        if (!chksuper())
  803. X          break;
  804. X        if (!formatscsidrive(unit,d[unit].blocksize,fuword((int *)arg)))
  805. X          u.u_error=EIO;
  806. X        /* fall to next case */
  807. X      case SCSIIOINITUNIT:
  808. X        initdrive(unit);
  809. X        break;
  810. X      case SCSIIOGETBLKSZ:
  811. X        suword((int *)arg,d[unit].blocksize);
  812. X        break;
  813. X      default:
  814. X        u.u_error=EINVAL;
  815. X        break;
  816. X    }
  817. X    return(0);
  818. }
  819. X
  820. int scsiprint()
  821. {
  822. X    printf("scsiprint called:\n");
  823. X    return(0);
  824. }
  825. SHAR_EOF
  826. echo 'File scsi.c is complete' &&
  827. chmod 0644 scsi.c ||
  828. echo 'restore of scsi.c failed'
  829. Wc_c="`wc -c < 'scsi.c'`"
  830. test 43689 -eq "$Wc_c" ||
  831.     echo 'scsi.c: original size 43689, current size' "$Wc_c"
  832. rm -f _shar_wnt_.tmp
  833. fi
  834. # ============= scsi.h ==============
  835. if test -f 'scsi.h' -a X"$1" != X"-c"; then
  836.     echo 'x - skipping scsi.h (File already exists)'
  837.     rm -f _shar_wnt_.tmp
  838. else
  839. > _shar_wnt_.tmp
  840. echo 'x - extracting scsi.h (Text)'
  841. sed 's/^X//' << 'SHAR_EOF' > 'scsi.h' &&
  842. /*
  843. X
  844. 9/16/90 Tin Le
  845. X    - Released to the world version 1.0
  846. X
  847. X    Modified for Interactive 386/ix v2.0.2 with some bug fixes
  848. X    and minor enhancements.
  849. X
  850. SCSI disk driver for unix system V (Microport system V/386)
  851. This driver uses the ST-01 controller.  This supports multiple initiators
  852. and multiple targets.
  853. X
  854. Copyright (c) 9.6.1988 Tatu Yl|nen
  855. Copyright (c) 16.9.1988 Tin Le
  856. X              All rights reserved.
  857. X
  858. */
  859. X
  860. #define SCSIMAXDRIVES  4   /* max # disk drives supported */
  861. #define SCSIMAXPARTS   16  /* max partitions/drive */
  862. X
  863. typedef struct scsidrivest
  864. {
  865. X  unsigned char drivename[64]; /* drive type identification string */
  866. X  int blocksize;  /* logical block size; if 0, not present */
  867. X  long capacity;  /* total disk capacity in blocks */
  868. X  unsigned char nomsgs;    /* set if drive does not support messages */
  869. X  int nparts;     /* # partitions */
  870. X  struct partst
  871. X    {
  872. X      long start; /* starting sector number */
  873. X      long len;   /* partition length */
  874. X    } parts[SCSIMAXPARTS];
  875. X
  876. X  unsigned char *xferbuf;  /* transfer buffer address */
  877. X  int xferlen;    /* data len to transfer */
  878. X  unsigned char *xfercmd;  /* command to transfer */
  879. X  char xferslow;  /* true if watch out for slow transfers */
  880. X  char xferstatus; /* status byte received from target */
  881. X  int xfertimeout; /* if nonzero, timeout in 1/10 sec */
  882. X  int xfertime;    /* if nonzero, elapsed time waiting (1/10 sec) */
  883. X  int xferretries; /* if nonzero, retry the current request and decrement*/
  884. X  char xferphys;   /* if true, transferring data with raw io */
  885. X  char xferpolled; /* if true, transfer must be polled */
  886. X
  887. X  unsigned char *savedbuf;  /* saved buffer */
  888. X  int savedlen;    /* saved lenght */
  889. X  unsigned char *savedcmd;  /* saved command */
  890. X
  891. X  unsigned char *origbuf;   /* original buffer */
  892. X  int origlen;     /* original length */
  893. X  unsigned char *origcmd;   /* original command */
  894. X
  895. X  struct buf *reqlist; /* queued requests */
  896. X  struct buf *currentbuf; /* buffer being executed */
  897. X
  898. X  char connected; /* true if connection to drive established */
  899. X  char busy;      /* true if currently executing a command */
  900. } SCSIDRIVE;
  901. X
  902. #define SCSIIOREADCAP  1 /* read capacity of partition or drive
  903. X                            (if part == 15); arg=&capacity */
  904. #define SCSIIOREADTYPE 2 /* read drive type name (as a string); arg=buf */
  905. #define SCSIIOFORMAT   3 /* reformat the drive; arg=&interleave */
  906. #define SCSIIOSETBLK   4 /* set drive block size for format; arg=&size */
  907. #define SCSIIOINITUNIT 5 /* re-initializes the unit, reading partition table */
  908. #define SCSIIOGETBLKSZ 6 /* read sector size */
  909. X
  910. /* Partitioning is done by writing on the first block of partition 15
  911. X   (the entire drive).  Note that drive block size may not be the same as
  912. X   system block size.  Partition table format: each entry 3 bytes start,
  913. X   3 bytes length (in blocks, msb first), terminated by 6 zeroes.  If first
  914. X   partition starts at 0, it will be moved to 1 automatically; this appears
  915. X   to be the convention under dos. */
  916. X
  917. /* External defines for scsi routines 8/13/90 TL */
  918. extern void scsiintr();
  919. extern void scsitick();
  920. extern scsiioctl();
  921. extern void scsiinit();
  922. extern void scsiopen();
  923. extern void scsiclose();
  924. extern void scsistrategy();
  925. extern void scsiread();
  926. extern void scsiwrite();
  927. extern void sendtoscsi();
  928. extern void getfromscsi();
  929. X
  930. /* ctypes defines for scsiinit() 8/20/90 TL */
  931. #define isspace(c)    ((c) == ' ' ? 1 : ((c) == '\t' ? 1 : \
  932. X            ((c) == '\n' ? 1 : ((c) == '\r' ? 1 : 0))))
  933. X
  934. #define isxdigit(c)    ((c) >= '0' && (c) <= '9' ? 1 : \
  935. X            ((c) >= 'a' && (c) <= 'f' ? 1 : \
  936. X            ((c) >= 'A' && (c) <= 'F' ? 1 : 0)))
  937. SHAR_EOF
  938. chmod 0644 scsi.h ||
  939. echo 'restore of scsi.h failed'
  940. Wc_c="`wc -c < 'scsi.h'`"
  941. test 3587 -eq "$Wc_c" ||
  942.     echo 'scsi.h: original size 3587, current size' "$Wc_c"
  943. rm -f _shar_wnt_.tmp
  944. fi
  945. # ============= scsiasm.s ==============
  946. if test -f 'scsiasm.s' -a X"$1" != X"-c"; then
  947.     echo 'x - skipping scsiasm.s (File already exists)'
  948.     rm -f _shar_wnt_.tmp
  949. else
  950. > _shar_wnt_.tmp
  951. echo 'x - extracting scsiasm.s (Text)'
  952. sed 's/^X//' << 'SHAR_EOF' > 'scsiasm.s' &&
  953. X    .file "scsiasm.s"
  954. /
  955. / fast transfer to/from the scsi controller
  956. /
  957. / Copyright (c) 1988 Tatu Yl|nen
  958. /               All rights reserved.
  959. /
  960. X
  961. X    .text
  962. X    .align    4
  963. X    .globl    getfromscsi
  964. X
  965. getfromscsi:
  966. X        pushl %ebp
  967. X        movl %esp,%ebp
  968. X        pushl %esi
  969. X        pushl %edi
  970. X    push %es
  971. X    movw %ds,%ax
  972. X    movw %ax,%es
  973. X        movl 8(%ebp),%edi
  974. X        movl 12(%ebp),%ecx
  975. X        movl scsidataport,%esi
  976. X    cld
  977. X    rep
  978. X    smovb
  979. X    pop %es
  980. X        popl %edi
  981. X        popl %esi
  982. X    popl %ebp
  983. X        ret
  984. X
  985. X        .globl  sendtoscsi
  986. sendtoscsi:
  987. X        pushl %ebp
  988. X        movl %esp,%ebp
  989. X        pushl %esi
  990. X        pushl %edi
  991. X    push %es
  992. X    movw %ds,%ax
  993. X    movw %ax,%es
  994. X        movl 8(%ebp),%esi
  995. X        movl 12(%ebp),%ecx
  996. X        movl scsidataport,%edi
  997. X    cld
  998. X    rep
  999. X    smovb
  1000. X    pop %es
  1001. X        popl %edi
  1002. X        popl %esi
  1003. X    popl %ebp
  1004. X        ret
  1005. SHAR_EOF
  1006. chmod 0644 scsiasm.s ||
  1007. echo 'restore of scsiasm.s failed'
  1008. Wc_c="`wc -c < 'scsiasm.s'`"
  1009. test 805 -eq "$Wc_c" ||
  1010.     echo 'scsiasm.s: original size 805, current size' "$Wc_c"
  1011. rm -f _shar_wnt_.tmp
  1012. fi
  1013. # ============= scsipart.c ==============
  1014. if test -f 'scsipart.c' -a X"$1" != X"-c"; then
  1015.     echo 'x - skipping scsipart.c (File already exists)'
  1016.     rm -f _shar_wnt_.tmp
  1017. else
  1018. > _shar_wnt_.tmp
  1019. echo 'x - extracting scsipart.c (Text)'
  1020. sed 's/^X//' << 'SHAR_EOF' > 'scsipart.c' &&
  1021. /*
  1022. X
  1023. SCSI disk partitioning program
  1024. X
  1025. Copyright (c) 9.6.1988 Tatu Yl|nen
  1026. Copyright (c) 16.9.1990 Tin Le
  1027. X              All rights reserved.
  1028. X
  1029. */
  1030. X
  1031. #include <stdio.h>
  1032. #include <fcntl.h>
  1033. #include "scsi.h"
  1034. X
  1035. #define DEV "/dev/rscsi%ds"    /* must be raw device to use ioctls */
  1036. #define BDEV "/dev/scsi%ds"    /* must be block device to use lseeks */
  1037. X
  1038. char cdevname[80];
  1039. char bdevname[80];
  1040. unsigned char drivename[80];
  1041. unsigned char buf[4096];
  1042. int capacity;
  1043. int interleave,blocksize;
  1044. X
  1045. int nparts;
  1046. long partstart[SCSIMAXPARTS];
  1047. long partlen[SCSIMAXPARTS];
  1048. X
  1049. int scsiunit;
  1050. int scsihandle;
  1051. int scsiblkhandle;
  1052. X
  1053. int asknumber(s,low,high)
  1054. char *s;
  1055. int low,high;
  1056. {
  1057. X  int a;
  1058. X
  1059. X  while (1)
  1060. X    {
  1061. X      printf("%s [%d-%d]: ",s, low, high);
  1062. X      if (scanf("%d",&a) == 1 && a >= low && a <= high)
  1063. X        return a;
  1064. X      printf("invalid input, try again.\n");
  1065. X      fflush(stdin);
  1066. X    }
  1067. }
  1068. X
  1069. readparts()
  1070. {
  1071. X  unsigned char *cp;
  1072. X
  1073. X  lseek(scsiblkhandle,0l,0);
  1074. X  if (read(scsiblkhandle,buf,1024) != 1024)
  1075. X    {
  1076. X      perror("Could not read partition table");
  1077. X      exit(1);
  1078. X    }
  1079. X  for (nparts=0,cp=(unsigned char *)buf;
  1080. X       cp[0] || cp[1] || cp[2] || cp[3] || cp[4] || cp[5];
  1081. X       nparts++,cp+=6)
  1082. X     {
  1083. X       if (nparts >= SCSIMAXPARTS-1)
  1084. X         {
  1085. X           printf("Invalid partition table - assuming no partitions\n");
  1086. X           nparts=0;
  1087. X           return;
  1088. X         }
  1089. X       partstart[nparts]=(cp[0] << 16) + (cp[1] << 8) + cp[2];
  1090. X       partlen[nparts]=(cp[3] << 16) + (cp[4] << 8) + cp[5];
  1091. X     }
  1092. }
  1093. X
  1094. saveparts()
  1095. {
  1096. X  int a;
  1097. X  unsigned char *cp;
  1098. X
  1099. X  for (a=0,cp=buf;a<nparts;a++,cp+=6)
  1100. X    {
  1101. X      cp[0]=partstart[a]>>16;
  1102. X      cp[1]=partstart[a]>>8;
  1103. X      cp[2]=partstart[a];
  1104. X      cp[3]=partlen[a]>>16;
  1105. X      cp[4]=partlen[a]>>8;
  1106. X      cp[5]=partlen[a];
  1107. X    }
  1108. X  memset(cp,0,6);
  1109. X  lseek(scsiblkhandle,0l,0);
  1110. X  if (write(scsiblkhandle,buf,1024) != 1024)
  1111. X    {
  1112. X      printf("error saving partition table\n");
  1113. X      exit(1);
  1114. X    }
  1115. }
  1116. X
  1117. int addpart(s,l)
  1118. long s,l;
  1119. {
  1120. X  if (nparts >= SCSIMAXPARTS-1)
  1121. X    {
  1122. X      printf("too many partitions\n");
  1123. X      return 0;
  1124. X    }
  1125. X  partstart[nparts]=s;
  1126. X  partlen[nparts]=l;
  1127. X  nparts++;
  1128. X  return 1;
  1129. }
  1130. X
  1131. int delpart(n)
  1132. int n;
  1133. {
  1134. X  int a;
  1135. X
  1136. X  if (n < 0 || n >= nparts)
  1137. X    {
  1138. X      printf("invalid partition number\n");
  1139. X      return 0;
  1140. X    }
  1141. X  for (a=n;a<nparts-1;a++)
  1142. X    {
  1143. X      partstart[a]=partstart[a+1];
  1144. X      partlen[a]=partlen[a+1];
  1145. X    }
  1146. X  nparts--;
  1147. X  return 1;
  1148. }
  1149. X
  1150. printparts()
  1151. {
  1152. X  int a;
  1153. X
  1154. X  printf("capacity=%ld.  Defined partitions:\n",capacity);
  1155. X  for (a=0;a<nparts;a++)
  1156. X    {
  1157. X      printf("  %d: start=%ld len=%ld blocks\n",a,partstart[a],partlen[a]);
  1158. X    }
  1159. X  if (nparts == 0)
  1160. X    printf("  no partitions defined.\n");
  1161. }
  1162. X
  1163. main()
  1164. {
  1165. X  int a;
  1166. X  long s,l;
  1167. X  int errcount=10;
  1168. X
  1169. X  printf("\nscsi disk drive formatting and partitioning utility  V1.0\n");
  1170. X  printf("Copyright (c) 9.6.1988 Tatu Yl|nen\n\n");
  1171. X  printf("Warning: It is easy to destroy data with this program.  Abort now\n");
  1172. X  printf("if you are not sure what you are doing.\n");
  1173. X  scsiunit=asknumber("Enter number of the scsi disk you wish to partition?",
  1174. X                     0,7);
  1175. X  sprintf(cdevname,DEV,scsiunit);
  1176. X  sprintf(bdevname,BDEV,scsiunit);
  1177. X  scsihandle=open(cdevname,O_RDWR);
  1178. X  if (scsihandle == -1)
  1179. X    {
  1180. X      perror(cdevname);
  1181. X      exit(1);
  1182. X    }
  1183. X  scsiblkhandle=open(bdevname,O_RDWR);
  1184. X  if (scsiblkhandle == -1)
  1185. X    {
  1186. X      perror(bdevname);
  1187. X      exit(1);
  1188. X    }
  1189. X  if (ioctl(scsihandle,SCSIIOREADTYPE,drivename) == -1)
  1190. X    perror("SCSIIOREADTYPE ioctl");
  1191. X  if (ioctl(scsihandle,SCSIIOREADCAP,&capacity) == -1)
  1192. X    perror("SCSIIOREADCAP ioctl");
  1193. X  if (ioctl(scsihandle,SCSIIOGETBLKSZ,&blocksize) == -1)
  1194. X    perror("SCSIIOGETBLKSZ ioctl");
  1195. X  printf("Drive %d: %d blocks, blocksize=%d\n",scsiunit,capacity,blocksize);
  1196. X  printf("%s\n",drivename);
  1197. X  printf("Do you wish to format the unit (y/n)?\n");
  1198. X  fflush(stdin);
  1199. X  gets(buf);
  1200. X  if (buf[0] == 'y' || buf[0] == 'Y')
  1201. X    {
  1202. X      printf("FORMATTING WILL DESTROY ALL AND ANY DATA ON THE DRIVE.\n");
  1203. X      printf("ARE YOU SURE YOU WANT TO DO THIS (Y/N)?\n");
  1204. X      gets(buf);
  1205. X      if (buf[0] != 'y' && buf[0] != 'Y')
  1206. X        exit(1);
  1207. X      blocksize=asknumber("Enter block size for the drive (usually 512)?",
  1208. X                          0,4096);
  1209. X      interleave=asknumber("Enter interleave factor for the drive (usually between 1 and 10)?",
  1210. X                           0,34);
  1211. X      while (ioctl(scsihandle,SCSIIOSETBLK,&blocksize) == -1 ||
  1212. X          ioctl(scsihandle,SCSIIOFORMAT,&interleave) == -1 && errcount-->0) ;
  1213. X    if (errcount <= 0)
  1214. X        {
  1215. X          perror("Format failure");
  1216. X          exit(1);
  1217. X        }
  1218. X      if (ioctl(scsihandle,SCSIIOREADCAP,&capacity) == -1)
  1219. X        perror("SCSIIOREADCAP ioctl");
  1220. X      nparts=0;
  1221. X      saveparts();
  1222. X      printf("Format complete.  Drive capacity is %d blocks.\n",capacity);
  1223. X    }
  1224. X  if (ioctl(scsihandle,SCSIIOINITUNIT,NULL) == -1)
  1225. X    perror("SCSIIOINITUNIT ioctl");
  1226. X  if (ioctl(scsihandle,SCSIIOREADTYPE,drivename) == -1)
  1227. X    perror("SCSIIOREADTYPE ioctl");
  1228. X  if (ioctl(scsihandle,SCSIIOREADCAP,&capacity) == -1)
  1229. X    perror("SCSIIOREADCAP ioctl");
  1230. X  if (ioctl(scsihandle,SCSIIOGETBLKSZ,&blocksize) == -1)
  1231. X    perror("SCSIIOGETBLKSZ ioctl");
  1232. X  if (!readparts())
  1233. X    nparts=0;
  1234. X  while (1)
  1235. X    {
  1236. X      printparts();
  1237. X      a=asknumber("1 add partition 2 delete partition 8 quit (no save) 9 save",
  1238. X                  1,9);
  1239. X      switch (a)
  1240. X        {
  1241. X          case 1: /* add partition */
  1242. X            s=asknumber("enter partition start in blocks?",0,capacity);
  1243. X            l=asknumber("enter partition length in blocks?",0,capacity-s);
  1244. X            addpart(s,l);
  1245. X            break;
  1246. X          case 2: /* delete partition */
  1247. X            a=asknumber("enter partition number to delete?",0,nparts-1);
  1248. X            delpart(a);
  1249. X            break;
  1250. X          case 8: /* quit no save */
  1251. X            printf("partition table not modified\n");
  1252. X            exit(1);
  1253. X          case 9: /* quit, save modifications */
  1254. X            printf("saving partition table\n");
  1255. X            saveparts();
  1256. X            if (ioctl(scsihandle,SCSIIOINITUNIT,NULL) == -1)
  1257. X              perror("SCSIIOINITUNIT ioctl");
  1258. X            exit(0);
  1259. X          default:
  1260. X            printf("invalid command\n");
  1261. X            break;
  1262. X        }
  1263. X    }
  1264. }
  1265. SHAR_EOF
  1266. chmod 0644 scsipart.c ||
  1267. echo 'restore of scsipart.c failed'
  1268. Wc_c="`wc -c < 'scsipart.c'`"
  1269. test 6168 -eq "$Wc_c" ||
  1270.     echo 'scsipart.c: original size 6168, current size' "$Wc_c"
  1271. rm -f _shar_wnt_.tmp
  1272. fi
  1273. # ============= scsipart.uu ==============
  1274. if test -f 'scsipart.uu' -a X"$1" != X"-c"; then
  1275.     echo 'x - skipping scsipart.uu (File already exists)'
  1276.     rm -f _shar_wnt_.tmp
  1277. else
  1278. > _shar_wnt_.tmp
  1279. echo 'x - extracting scsipart.uu (Text)'
  1280. sed 's/^X//' << 'SHAR_EOF' > 'scsipart.uu' &&
  1281. begin 755 scsipart
  1282. M3 $$ $--]";(<P  ;P(  !P  P$+ 0  '$@  &0=  "$&P  U    -    #L
  1283. M"$  +G1E>'0   #0    T    !Q(  #0                    (    "YD
  1284. M871A    [ A  .P(0 !D'0  [$@                  $     N8G-S    
  1285. M % F0 !0)D  A!L                       "     +F-O;6UE;G0     
  1286. M     '@-  !09@                    (  ,.0D)"#[ B+[(M%"(U4A1")
  1287. M%>P(0 !2C54,4E#HW____VH Z. S  "#Q 3H] ,  (/$#%#HQT<  &H N $ 
  1288. M  ":      < ],.0D)#K7?]U$/]U#/]U"&@4"4  Z*\)  "#Q!"-1?Q0:"$)
  1289. M0 #H/@H  (/$"#T!    =16+10PY1?Q\#8M%$#E%_'\%BT7\ZQAH) E  .AU
  1290. M"0  66AX(4  Z)8]  !9ZZ7)PU6+[%#KG9"0D.DR 0  D&H :@#_-=@W0 #H
  1291. MOQT  (/$#&@ !   :$ G0 #_-=@W0 #H6T8  (/$##T !   =!-H/PE  .B?
  1292. M"   66H!Z -'  !9QP5,-T       ,=%_$ G0 #IB    )"X#P   #D%3#= 
  1293. M 'P;:%X)0 #HY @  %G'!4PW0       Z:T   "0H4PW0 "+5?P/MA+!XA"+
  1294. M3?P/MDD!P>$( ]&+3?P/MDD" ]&)%(50-T  H4PW0 "+5?P/ME(#P>(0BTW\
  1295. M#[9)!,'A" /1BTW\#[9)!0/1B12%D#=  /\%3#=  (-%_ :+1?R .  /A6W_
  1296. M__^+1?R > $ #X5@____BT7\@'@"  ^%4____XM%_(!X P /A4;___^+1?R 
  1297. M> 0 #X4Y____BT7\@'@%  ^%+/___\G#58OL4.G&_O__Z>(   "0QT7\    
  1298. M ,=%^$ G0 #K<HM%^(M5_(L4E5 W0 #!^A"($(M%^(M5_(L4E5 W0 #!^@B(
  1299. M4 &+1?B+5?R*%)50-T  B% "BT7XBU7\BQ25D#=  ,'Z$(A0 XM%^(M5_(L4
  1300. ME9 W0 #!^@B(4 2+1?B+5?R*%)60-T  B% %_T7\@T7X!J%,-T  .47\?(1J
  1301. M!FH _W7XZ%Y$  "#Q QJ &H _S78-T  Z.0;  "#Q QH  0  &A )T  _S78
  1302. M-T  Z"1%  "#Q P]  0  '03:) )0 #H0 <  %EJ >@H10  6<G#58OL@^P(
  1303. MZ13___^0D.M,N \    Y!4PW0 !\$FBN"4  Z \'  !9N     #K*Z%,-T  
  1304. MBU4(B12%4#=  *%,-T  BU4,B12%D#=  /\%3#=  +@!    ZP#)PU6+[.NO
  1305. MD.MQ@WT( 'P*H4PW0  Y10A\$FC#"4  Z+@&  !9N     #K38M%"(E%_.LM
  1306. MBT7\BU7\0HL4E5 W0 ")%(50-T  BT7\BU7\0HL4E9 W0 ")%(60-T  _T7\
  1307. MH4PW0 !(.47\?,C_#4PW0 "X 0   .L R<-5B^Q0ZXF0D)#K8_\U0#=  &C=
  1308. M"4  Z$8&  "#Q C'1?P     ZR>+1?S_-(60-T  BT7\_S2%4#=  /]U_&@!
  1309. M"D  Z!D&  "#Q!#_1?RA3#=  #E%_'S/@SU,-T   '4+:"$*0 #H]@4  %G)
  1310. MPU6+[%#KEY#IFP0  )#'1? *    :#L*0 #HU04  %EH=PI  .C*!0  66B<
  1311. M"D  Z+\%  !9:-\*0 #HM 4  %EJ!VH : @+0 #HX?O__X/$#*/0-T  _S70
  1312. M-T  :#T+0 !H4"9  .@$$P  @\0,_S70-T  :$L+0 !HH"9  .CL$@  @\0,
  1313. M:@)H4"9  .AY0@  @\0(H]0W0 "X_____SD%U#=  '43:% F0 #HQ@0  %EJ
  1314. M >@J0P  66H":* F0 #H14(  (/$"*/8-T  N/____\Y!=@W0 !U$VB@)D  
  1315. MZ)($  !9:@'H]D(  %EH\"9  &H"_S74-T  Z+,]  "#Q P]_____W4+:%@+
  1316. M0 #H8P0  %EH0#=  &H!_S74-T  Z(P]  "#Q P]_____W4+:&T+0 #H/ 0 
  1317. M %EH2#=  &H&_S74-T  Z&4]  "#Q P]_____W4+:($+0 #H%00  %G_-4@W
  1318. M0 #_-4 W0 #_-= W0 !HE@M  .AT!   @\00:/ F0 !HN0M  .AB!   @\0(
  1319. M:+T+0 #H500  %EH>"%  .AV.   66A )T  Z/\"  !9#[8%0"=  #UY    
  1320. M=!(/M@5 )T  /5D    /A1H!  !HY M  .@4!   66@<#$  Z D$  !9:$ G
  1321. M0 #HO@(  %D/M@5 )T  /7D   !T%@^V!4 G0  ]60   '0(:@'HRD$  %EH
  1322. M !   &H :$4,0 #H!/K__X/$#*-(-T  :B)J &AS#$  Z.[Y__^#Q RC1#= 
  1323. M .L :$@W0 !J!/\UU#=  .A6/   @\0,/?____]TY&A$-T  :@/_-=0W0 #H
  1324. M.CP  (/$##W_____=0J+1?#_3?"%P'^^@WWP '\3:+4,0 #HV@(  %EJ >@^
  1325. M00  66A -T  :@'_-=0W0 #H^SL  (/$##W_____=0MHQ Q  .BK @  6<<%
  1326. M3#=       #H^_K___\U0#=  &C8#$  Z <#  "#Q AJ &H%_S74-T  Z+4[
  1327. M  "#Q P]_____W4+: @-0 #H90(  %EH\"9  &H"_S74-T  Z(X[  "#Q P]
  1328. M_____W4+:!T-0 #H/@(  %EH0#=  &H!_S74-T  Z&<[  "#Q P]_____W4+
  1329. M:#(-0 #H%P(  %EH2#=  &H&_S74-T  Z$ [  "#Q P]_____W4+:$8-0 #H
  1330. M\ $  %GH"OG__X7 =0K'!4PW0       Z/O[__]J"6H!:%L-0 #H@?C__X/$
  1331. M#(E%_(M%_.G(    D/\U0#=  &H :)8-0 #H8/C__X/$#(E%^*% -T  *T7X
  1332. M4&H :+<-0 #H1?C__X/$#(E%]/]U]/]U^.C0^O__@\0(Z9T   "0H4PW0 !(
  1333. M4&H :-D-0 #H&/C__X/$#(E%_/]U_.CZ^O__6>MX:/L-0 #HP0$  %EJ >BI
  1334. M/P  66@9#D  Z*X!  !9Z(SY__]J &H%_S74-T  Z%DZ  "#Q P]_____W4+
  1335. M:#$.0 #H"0$  %EJ .AM/P  66A&#D  Z'(!  !9ZQPM 0   'SL/0@   !W
  1336. MY3T     ?-[_)(7P"$  Z?;^___)PU6+[(/L$.E;^___D%6+[(/L"%=64XMU
  1337. M"(EU^(,]>"%   !_,&AX(4  Z*X-  !9/?____]U$CEU^ ^%A@   #/ 6UY?
  1338. MR<.0D/\-?"%  /\%>"%  (L]>"%  %=J"O\U?"%  %;H0P$  (/$$(7 B]AT
  1339. M!(O[*_Z+QP/P*05X(4   3U\(4  @SUX(4   'T%,\#K!I"A>"%   ^^%84A
  1340. M0 "+%)4\)4  *Q5\(4  .]!]"VAX(4  Z#TX  !9A=L/A%?___].Q@8 BT7X
  1341. M6UY?R<-5B^Q75K]8#D  H:@00  Y!3 F0 !]#*$P)D  BSR%; Y  /]U".@)
  1342. M/@  68OPA?9T'U;_=0AJ N@//@  @\0,:@)H9@Y  &H"Z/X]  "#Q Q7Z-T]
  1343. M  !94%=J NCK/0  @\0,:@%H:0Y  &H"Z-H]  "#Q Q>7\G#D)"058OL4%>-
  1344. M10R+T ^^!90A0 "I @   '45#[X%E"%  *F     ="B #90A0  ":(@A0 !2
  1345. M_W4(Z%D5  "#Q R+^ ^^!90A0 "I(    '0*N/____]?R<.0D(O'7\G#D)"0
  1346. M5U:+?"0,BW0D$(I4)!2+3"0827PFK*HZPG0;27P=K*HZPG0227P4K*HZPG0)
  1347. M27P+K*HZPG7<B\=>7\,SP%Y?PU6+[%"-10R+T%+_=0AH>"%  .AA    @\0,
  1348. MR<-5B^Q0C440B]!2_W4,_W4(Z$<   "#Q S)PY"058OL@^P45U:+?0B-11"+
  1349. M\,9%^ &+QXE%](E%\%?HOCP  %F)1>S&1?D\5O]U#(U%[%#H"0   (/$#%Y?
  1350. MR<.0D%6+[('L% $  %=64XM]"(MU#,>%_/[__P    #'!:090       QP6H
  1351. M&4       .F; @  D)"0_PVD&4  5_^U]/[__^@J$P  @\0(/?____\/A) !
  1352. M  #I?0(  )"0D(/[*G43QX7P_O__      ^V!D:+V.L+D,>%\/[__P$   #'
  1353. MA?C^__\     ZQR0D&N%^/[__PH#PRTP    B87X_O__#[8&1HO8#[:#E1Q 
  1354. M *D$    ==B#O?C^__\ =0K'A?C^______]_B\.)A>S^__\];    '0)@[WL
  1355. M_O__:'4&#[8&1HO8A=L/A,D!  "#^UMU&HV% /___U!6Z"D(  "#Q B%P(OP
  1356. M#X2J 0  #[:#E1Q  *D!    =!/'A>S^__]L    #[:#EAU  (O8@_MN=%^#
  1357. M/:@90   =5:#^V-T48/[6W1,_P6D&4  _P]]"5?H'PH  %GK"8M'! ^V /]'
  1358. M!(F%]/[__P^V@)4<0 "I"    '70_PVD&4  5_^U]/[__^CI$0  @\0(/?__
  1359. M__]T4XO#/5L   !T)#UC    =!T]:0    ^$N    #UN    =$D]<P    ^%
  1360. MI@   (U%$%!7C84 ____4/^U^/[__U/_M?#^___H, 8  .F@    D)"0@[W\
  1361. M_O__  ^%Y0   +C_____6UY?R<.0@[WL_O__:'4?BT40!00   ")11"+0/QF
  1362. MBQ6D&4  9HD0Z:H   "0D(.][/[__VQU'XM%$ 4$    B440BT#\BQ6D&4  
  1363. MB1#IA    )"0D)"+11 %!    (E%$(M _(L5I!E  (D0ZVB-11!05_^U[/[_
  1364. M__^U^/[__U/_M?#^___H&P$  (/$&(F%[/[__X.][/[__P!T$8N%\/[__P&%
  1365. M_/[__^LKD)"0@SVH&4   '03@[W\_O__ '4*N/____];7E_)PXN%_/[__UM>
  1366. M7\G#D ^V!D:%P(O8=0Z+A?S^__];7E_)PY"0D ^V@Y4<0 "I"    '1F@SVH
  1367. M&4   '71_P6D&4  _P]]"U?H:0@  %GK"Y"0BT<$#[8 _T<$B87T_O__#[: 
  1368. ME1Q  *D(    =<[_#:090 !7_[7T_O__Z#$0  "#Q @]_____W6#QP6H&4  
  1369. M 0   .ET____@_LE=0\/M@9&B]B#^R4/A?#\____!:090 #_#WT*5^CX!P  
  1370. M6>L*D(M'! ^V /]'!(F%]/[__SO##X6=_/__Z3#___]5B^R#[&A75E.+?1B-
  1371. M1<"+\,=%M     #'1;      QT6L     ,=%J     #'1:0     QT6@    
  1372. M (M%#"UD    ?$<]%    '= A<!\//\DA:P90 "0_T6HQT6X"@   .L3QT6X
  1373. M"    .L*D)"0QT6X$    /\%I!E  /\/?1-7Z%$'  !9ZQ.0D#/ 6UY?R<.0
  1374. MBT<$#[8 _T<$B]@]*P   '09/2T   !T#STP    =#SIT@(  )"0D/]%I/]-
  1375. M$ ^.PP(  /\%I!E  /\/?0I7Z  '  !9ZPJ0BT<$#[8 _T<$B]B#^S /A9L"
  1376. M  "#?0QI#X61 @  @WT0 0^.AP(  /\%I!E  /\/?0I7Z,0&  !9ZPJ0BT<$
  1377. M#[8 _T<$B$6_#[[ /7@   !T#P^^1;\]6     ^%VP    ^^1PT]/    '0%
  1378. M@S\ ="/_!:090 #_#WT)5^A[!@  6>L)BT<$#[8 _T<$B$6^ZRR0D&H!5@^^
  1379. M1PU0Z/<V  "#Q P] 0   '4)B@:(1;[K!I"0QD6^__\%I!E   ^^1;X/MH"5
  1380. M'$  J8    !T/,=%N!    "#?1 "?Q__#:090 !7#[Y%OE#H"@X  (/$"/]-
  1381. M$.FV 0  D)"0#[Y%OHO8@VT0 NFD 0  D/\-I!E  %</OD6^4.C;#0  @\0(
  1382. SHAR_EOF
  1383. true || echo 'restore of scsipart.uu failed'
  1384. fi
  1385. echo 'End of  part 3'
  1386. echo 'File scsipart.uu is continued in part 4'
  1387. echo 4 > _shar_seq_.tmp
  1388. exit 0
  1389. -- 
  1390. +-----------------------------------------------------------------
  1391.  Station Zebra     ....!{claris,zorch}!szebra!tin
  1392.  Sunnyvale, CA      (408) 739-1520  24hrs Telebit+ 300-19200bps
  1393.                     Pub *NIX, Usenet and mail (no fee)
  1394.